package server;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.ArrayList;

import logic.Message;

import GUI.Server_GUI;

import ocsf.server.ConnectionToClient;
import ocsf.server.ObservableServer;

/**
 * Constructor
 * @author adahan2
 */
public class OBL_Server extends ObservableServer {

	public  final static int DEFAULT_PORT = 6000;
	
	private DB_Manager DB;
	
	public MemberController memberController;
	public BookController bookController;
	private LoanController loanController;
	private OrderController orderController;
	private ReportController reportController;
	private MessageController messageController;
	@SuppressWarnings("unused")
	private Scheduler scheduler;
	
	public String logger = "";

	public Server_GUI gui;
		
	public OBL_Server(int port,Server_GUI gui) {
		super(port);
		this.gui = gui;

	}
	
	public String InitDB(String user,String pass){
		try 
		{
            Class.forName("com.mysql.jdbc.Driver").newInstance();
        } catch (Exception ex) {/* handle the error*/}
        
        try 
        {
        	Connection DB_Connection = DriverManager.getConnection("jdbc:mysql://localhost/OBL",user,pass);
        	DB = new DB_Manager(DB_Connection,this);
        	
        	memberController = new MemberController(this, DB);
        	bookController = new BookController(this, DB);
        	loanController = new LoanController(this, DB);
        	orderController = new OrderController(this, DB);
        	reportController = new ReportController(this, DB);
        	messageController = new MessageController(this, DB);
        	
        	scheduler = new Scheduler(this,DB);
        	
            return "Server up!";

     	} catch (SQLException ex) 
     	    {/* handle any errors*/
            System.out.println("SQLException: " + ex.getMessage());
            System.out.println("SQLState: " + ex.getSQLState());
            System.out.println("VendorError: " + ex.getErrorCode());
            return "SQL Server error";
            }
	}
	

	@Override
	protected void clientConnected(ConnectionToClient client) {
		//if (gui.displayLoggedUsers) gui.DisplayLoggedUsers();
	}
	
	@Override
	synchronized protected void clientDisconnected(
			    ConnectionToClient client) {
		if (this.gui.displayLoggedUsers) gui.DisplayLoggedUsers();
	}
	
	
	/**
	 * Function to handle all incomming messages from clients - from OCSF
	 * @param msg - the Message object
	 * @param client - client which sent the message
	 */
	@Override
	protected void handleMessageFromClient(Object msg, ConnectionToClient client) {
		
		
		Message received = (Message)msg;
		ArrayList<String> index = received.GetMessageIndexes();
		ArrayList<Object> data = received.GetMessageData();
		
		switch(received.GetAction()){ //handles all kind of messages from client
		
		case Message.LOGIN_REQUEST:{
			if (index.get(0).equals("systemuser")){
				memberController.LoginSystemUser(client);
			}else{
				memberController.Login((String)data.get(0),(String)data.get(1),client);
			}
			
			if (this.gui.displayLoggedUsers) gui.DisplayLoggedUsers();
			break;
		}
		
		case Message.LOGOFF_REQUEST:{
			memberController.Logoff((String)data.get(0));
			//try{
				//client.close();
				//if (this.gui.displayLoggedUsers) gui.DisplayLoggedUsers();
			//}catch (IOException io){}
			break;
		}
		
		case Message.CREATE_MEMBER_REQUEST:{
			memberController.CreateMember(received,client);
			break;
		}
		
		case Message.SEARCH_MEMBER_REQUEST:{
			memberController.SearchMember(received, client);
			break;
		}
		
		case Message.ADD_BOOK_REQUEST:{
			bookController.CreateBook(received, client);
			break;
		}
		
		case Message.UPDATE_BOOK_REQUEST:{
			bookController.UpdateBook(received,client);
			break;
		}
		
		case Message.DELETE_BOOK_REQUEST:{
			bookController.DeleteBook(received,client);
			break;
		}
		
		case Message.SEARCH_BOOK_REQUEST:{
			bookController.SearchBook(received, client);
			break;
		}
		case Message.SEARCH_LOAN_REQUEST:{
			loanController.SearchLoan(received, client);
			break;
		}
		
		case Message.SEARCH_ORDER_REQUEST:{
			orderController.SearchOrder(received, client);
			break;
		}
		
		case Message.CREATE_LOAN_REQUEST:{
			loanController.CreateLoan(received, client);
			break;
		}
		
		case Message.CREATE_ORDER_REQUEST:{
			orderController.CreateOrder(received, client);
			break;
		}
		
		case Message.RETUREN_BOOK_REQUEST:{
			loanController.ReturnBook(received, client);
			break;
		}
		
		
		
		case Message.LATE_RETURN_REPORT_REQUEST:{
			reportController.CreateLateReturnReport(received, client);
			break;
		}
		
		case Message.LOAN_REPORT_REQUEST:{
			reportController.CreateLoanReport(received, client);
			break;
		}
		
		case Message.LATE_RETURN_REPORT_BOOK_REQUEST:{
			reportController.CreateLateReturnReportByBook(received, client);
			break;
		}
		
		case Message.LATE_RETURN_REPORT_CATEGORY_REQUEST:{
			reportController.CreateLateReturnReportByCategory(received, client);
			break;
		}
		
		case Message.ACTIVITY_REPORT_REQUEST:{
			//reportController.SearchActivityReports(received, client);
			//TODO refer to getactivity report
			break;
		}
		
		case Message.DELETE_MESSAGE_REQUEST:{
			messageController.DeleteMessage(received, client);
			break;
		}
		
		case Message.READ_MESSAGE_REQUEST:{
			messageController.SetReadMessage(received, client);
			break;
		}
		
		case Message.GET_MESSAGES_REQUEST:{
			messageController.GetSystem_Message((Integer)received.GetMessageData().get(0),client);
			break;
		}
		
		case Message.FREEZE_MEMBER_REQUEST:{
			memberController.SetMemberCardStatus(received);
			break;
		}
		
		case Message.UPDATE_MEMBER_REQUEST:{
			memberController.UpdateBook(received, client);
			break;
		}

		case Message.SEARCH_WORKER_REQUEST:{
			memberController.SearchWorker(received, client);
			break;
		}
		
		case Message.EXTEND_LOAN_REQUEST:{
			loanController.ExtendLoan(received, client);
			break;
		}
		
		case Message.CANCEL_ORDER_REQUEST:{
			orderController.CancelOrder(received,client);
			break;
		}
		
		case Message.PDF_REQUEST:{
			bookController.SendPDF(received,client);
			break;
		}
		
		}
	}
	
	
	/**
	 * This function adds the inserted text into the log
	 * @param text - the text to add
	 */
	public synchronized void Log(String text){
		this.logger += text + "\n";
		gui.DisplayLog();
	}
	
}
